﻿#include "ssServerSelect.h"

namespace StarSeeker
{

ssServerSelect::ssServerSelect()
{
	m_sendSize = 0;
	m_recvSize = 0;
	m_enable = false;
	m_nfds = 0;
	m_isBlock = false;
	m_session = 0;
	m_outTime = 0;
}

ssServerSelect::~ssServerSelect()
{
}

bool ssServerSelect::InitParam( u32 sendSize, u32 recvSize, time_t outTime)
{
	m_sendSize = sendSize;
	m_recvSize = recvSize;
	m_outTime = outTime;
	m_enable = true;
	return true;
}

bool32 ssServerSelect::CreateListenSocket(bool isV6, const char* ip, u16 port )
{
	return m_sListen.Listen(isV6, 0, ip, port);
}

void ssServerSelect::BeforeFDSET()
{
	ClearFDSet();
	if (!m_sListen.IsInvalidSocket())
	{
		AppendReadFDSet(m_sListen.GetSocket());
	}
	ssList<ssClientSocket>::Iterator it = m_sClient.Begin();
	while (it.IsVaild())
	{
		if (!(*it).IsInvalidSocket())
		{
			AppendReadFDSet((*it).GetSocket());
			AppendWriteFDSet((*it).GetSocket());
			AppendExceptFDSet((*it).GetSocket());
		}
		++it;
	}
}

void ssServerSelect::ProcessFDSET()
{
	if (!m_sListen.IsInvalidSocket() && IsReadSet(m_sListen.GetSocket()))
	{
		SockAddr_u addr;
		SOCKET s = AcceptListen(m_sListen.GetSocket(), &addr.addrin);
		if (s!=INVALID_SOCKET)
		{
			//Nonblock(s);
			if (m_sClient.Size() < FD_SETSIZE-1)
			{
				++m_session;
				if (m_session > 4000000000) m_session = 1;
				ssClientSocket* ps = m_sClient.Allot();
				ps->Detach();
				ps->InitBuffer(m_sendSize, m_recvSize);
				ps->Attach(s, addr, m_session);
				ps->m_createTime = ::time(0);
				OnNewConnect(*ps);
			}
			else
			{
				CloseOneSocket(s);
			}
		}
	}

	ssList<ssClientSocket>::Iterator it = m_sClient.Begin();
	while (it.IsVaild())
	{
		if (!(*it).IsInvalidSocket() && IsReadSet((*it).GetSocket()))
		{
			if ((*it).RecvBuffer() < 0)
			{
				OnDisconnect((*it));
				(*it).Detach();
			}
			else
			{
				if ((*it).m_recvBuf.Size() > 0)
				{
					OnReceive((*it));
					(*it).m_recvBuf.Empty();
				}
			}
		}
		++it;
	}
}

void ssServerSelect::AfterFDSET()
{
	time_t now = ::time(0);
	ssList<ssClientSocket>::Iterator it = m_sClient.Begin();
	while (it.IsVaild())
	{
		if ((*it).IsInvalidSocket())
		{
			it = m_sClient.EraseItr(it);
		}
		else if (m_outTime > 0 && now - (*it).m_createTime > m_outTime)
		{
			OnDisconnect((*it));
			(*it).Detach();
		}
		else
		{
			++it;
		}
	}
}

}
